home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb-4.5 / dist / gdb / m88k-pinsn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-03  |  9.0 KB  |  358 lines

  1. /* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
  2.    Copyright 1986, 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
  3.    Contributed by Data General Corporation, November 1989.
  4.    Partially derived from an earlier printcmd.c.
  5.  
  6. This file is part of GDB and the GNU Binutils.
  7.  
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12.  
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  21.  
  22. #include "defs.h"
  23. #include "opcode/m88k.h"
  24. #include "symtab.h"
  25.  
  26. void sprint_address ();
  27.  
  28. INSTAB  *hashtable[HASHVAL] = {0};
  29.  
  30. /*
  31. *        Disassemble an M88000 Instruction
  32. *
  33. *
  34. *       This module decodes the first instruction in inbuf.  It uses the pc
  35. *    to display pc-relative displacements.  It writes the disassembled
  36. *    instruction in outbuf.
  37. *
  38. *            Revision History
  39. *
  40. *       Revision 1.0    11/08/85        Creation date by Motorola
  41. *            05/11/89    R. Trawick adapted to GDB interface.
  42. */
  43. #define MAXLEN 20
  44.  
  45. print_insn (memaddr, stream)
  46.      CORE_ADDR memaddr;
  47.      FILE *stream;
  48. {
  49.   unsigned char buffer[MAXLEN];
  50.   /* should be expanded if disassembler prints symbol names */
  51.   char outbuf[100];
  52.   int n;
  53.  
  54.   /* Instruction addresses may have low two bits set. Clear them.    */
  55.   memaddr&= 0xfffffffc;
  56.   read_memory (memaddr, buffer, MAXLEN);
  57.  
  58.   n = m88kdis ((int)memaddr, buffer, outbuf);
  59.  
  60.   fputs (outbuf, stream);
  61.  
  62.   return (n);
  63. }
  64.  
  65. /*
  66.  * disassemble the first instruction in 'inbuf'.
  67.  * 'pc' should be the address of this instruction, it will
  68.  *   be used to print the target address if this is a relative jump or call
  69.  * 'outbuf' gets filled in with the disassembled instruction.  It should
  70.  *   be long enough to hold the longest disassembled instruction.
  71.  *   100 bytes is certainly enough, unless symbol printing is added later
  72.  * The function returns the length of this instruction in bytes.
  73.  */
  74.  
  75. int m88kdis( pc, inbuf, outbuf )
  76.  
  77.     int        pc;
  78.     int            *inbuf;
  79.     char    *outbuf;
  80.  
  81. {   static        ihashtab_initialized = 0;
  82.     int            instruction;
  83.     unsigned int    opcode;
  84.     INSTAB        *entry_ptr;
  85.     int                opmask;
  86.     int            class;
  87.  
  88.     instruction= *inbuf;
  89.  
  90.     if (!ihashtab_initialized) {
  91.     init_disasm();
  92.     }
  93.  
  94.     /* create a the appropriate mask to isolate the opcode */
  95.     opmask= DEFMASK;
  96.     class= instruction & DEFMASK;
  97.     if ((class >= SFU0) && (class <= SFU7)) {
  98.     if (instruction < SFU1) {
  99.         opmask= CTRLMASK;
  100.     } else {
  101.         opmask= SFUMASK;
  102.     }
  103.     } else if (class == RRR) {
  104.     opmask= RRRMASK;
  105.     } else if (class == RRI10) {
  106.     opmask= RRI10MASK;
  107.     }
  108.  
  109.     /* isolate the opcode */
  110.     opcode= instruction & opmask;
  111.  
  112.     /* search the hash table with the isolated opcode */
  113.     for (entry_ptr= hashtable[ opcode % HASHVAL ];
  114.      (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
  115.      entry_ptr= entry_ptr->next) {
  116.     }
  117.  
  118.     if (entry_ptr == NULL) {
  119.     sprintf( outbuf, "word\t%08x", instruction );
  120.     } else {
  121.     sprintf( outbuf, "%s\t", entry_ptr->mnemonic );
  122.     sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op1), instruction, pc, 1 );
  123.     sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op2), instruction, pc, 0 );
  124.     sprintop( &outbuf[strlen(outbuf)], &(entry_ptr->op3), instruction, pc, 0 );
  125.     }
  126.  
  127.  
  128.     return 4;
  129. }
  130.  
  131.  
  132. /*
  133. *                      Decode an Operand of an Instruction
  134. *
  135. *            Functional Description
  136. *
  137. *       This module formats and writes an operand of an instruction to buf
  138. *       based on the operand specification.  When the first flag is set this
  139. *       is the first operand of an instruction.  Undefined operand types
  140. *       cause a <dis error> message.
  141. *
  142. *            Parameters
  143. *    char    *buf        buffer where the operand may be printed
  144. *       OPSPEC  *opptr          Pointer to an operand specification
  145. *       UINT    inst            Instruction from which operand is extracted
  146. *    UINT    pc        PC of instruction; used for pc-relative disp.
  147. *       int     first           Flag which if nonzero indicates the first
  148. *                               operand of an instruction
  149. *
  150. *            Output
  151. *
  152. *       The operand specified is extracted from the instruction and is
  153. *       written to buf in the format specified. The operand is preceded
  154. *       by a comma if it is not the first operand of an instruction and it
  155. *       is not a register indirect form.  Registers are preceded by 'r' and
  156. *       hex values by '0x'.
  157. *
  158. *            Revision History
  159. *
  160. *       Revision 1.0    11/08/85        Creation date
  161. */
  162.  
  163. sprintop( buf, opptr, inst, pc, first )
  164.  
  165.    char   *buf;
  166.    OPSPEC *opptr;
  167.    UINT   inst;
  168.    int      pc;
  169.    int    first;
  170.  
  171. {  int      extracted_field;
  172.    char      *cond_mask_sym;
  173.    char      cond_mask_sym_buf[6];
  174.  
  175.    if (opptr->width == 0)
  176.       return;
  177.  
  178.    switch(opptr->type) {
  179.       case CRREG:
  180.                if (!first)
  181.                *buf++= ',';
  182.                sprintf( buf, "cr%d", UEXT(inst,opptr->offset,opptr->width));
  183.                break;
  184.  
  185.       case FCRREG:
  186.                if (!first)
  187.                *buf++= ',';
  188.                sprintf( buf, "fcr%d", UEXT(inst,opptr->offset,opptr->width));
  189.                break;
  190.  
  191.       case REGSC:
  192.                sprintf( buf, "[r%d]", UEXT(inst,opptr->offset,opptr->width));
  193.                break;
  194.  
  195.       case REG:
  196.                if (!first)
  197.                *buf++= ',';
  198.                sprintf( buf, "r%d", UEXT(inst,opptr->offset,opptr->width));
  199.                break;
  200.  
  201.       case HEX:
  202.                 if (!first)
  203.                *buf++= ',';
  204.                 extracted_field= UEXT(inst, opptr->offset, opptr->width);
  205.                 if (extracted_field == 0) {
  206.                 sprintf( buf, "0" );
  207.                 } else {
  208.                 sprintf( buf, "0x%02x", extracted_field );
  209.                 }
  210.                 break;
  211.  
  212.       case CONDMASK:
  213.                 if (!first)
  214.                *buf++= ',';
  215.                 extracted_field= UEXT(inst, opptr->offset, opptr->width);
  216.                 switch (extracted_field & 0x0f) {
  217.               case 0x1:    cond_mask_sym= "gt0";
  218.                     break;
  219.               case 0x2:    cond_mask_sym= "eq0";
  220.                     break;
  221.               case 0x3:    cond_mask_sym= "ge0";
  222.                     break;
  223.               case 0xc:    cond_mask_sym= "lt0";
  224.                     break;
  225.               case 0xd:    cond_mask_sym= "ne0";
  226.                     break;
  227.               case 0xe:    cond_mask_sym= "le0";
  228.                     break;
  229.               default:    cond_mask_sym= cond_mask_sym_buf;
  230.                     sprintf( cond_mask_sym_buf,
  231.                          "%x",
  232.                          extracted_field );
  233.                     break;
  234.             }
  235.             strcpy( buf, cond_mask_sym );
  236.             break;
  237.             
  238.       case PCREL:
  239.                 if (!first)
  240.                *buf++= ',';
  241.             sprint_address( pc + 4*(SEXT(inst,opptr->offset,opptr->width)),
  242.                     buf );
  243.                 break;
  244.  
  245.       case CONT:
  246.                sprintf( buf,
  247.                 "%d,r%d",
  248.                 UEXT(inst,opptr->offset,5),
  249.                     UEXT(inst,(opptr->offset)+5,5) );
  250.                break;
  251.  
  252.       case BF:
  253.                if (!first)
  254.                *buf++= ',';
  255.                sprintf( buf,
  256.                 "%d<%d>",
  257.                 UEXT(inst,(opptr->offset)+5,5),
  258.                     UEXT(inst,opptr->offset,5));
  259.                break;
  260.  
  261.       default:
  262.                sprintf( buf, "<dis error: %08x>", inst );
  263.     }
  264.  
  265. }
  266.  
  267. /*
  268. *                 Initialize the Disassembler Instruction Table
  269. *
  270. *       Initialize the hash table and instruction table for the disassembler.
  271. *       This should be called once before the first call to disasm().
  272. *
  273. *            Parameters
  274. *
  275. *            Output
  276. *
  277. *       If the debug option is selected, certain statistics about the hashing
  278. *       distribution are written to stdout.
  279. *
  280. *            Revision History
  281. *
  282. *       Revision 1.0    11/08/85        Creation date
  283. */
  284.  
  285. init_disasm()
  286. {
  287.    int i,size;
  288.  
  289.    for (i=0 ; i < HASHVAL ; i++)
  290.       hashtable[i] = NULL;
  291.  
  292.    for (i=0, size =  sizeof(instructions) / sizeof(INSTAB) ; i < size ;
  293.        install(&instructions[i++]));
  294.  
  295. }
  296.  
  297. /*
  298. *       Insert an instruction into the disassembler table by hashing the
  299. *       opcode and inserting it into the linked list for that hash value.
  300. *
  301. *            Parameters
  302. *
  303. *       INSTAB *instptr         Pointer to the entry in the instruction table
  304. *                               to be installed
  305. *
  306. *       Revision 1.0    11/08/85        Creation date
  307. *            05/11/89    R. TRAWICK ADAPTED FROM MOTOROLA
  308. */
  309.  
  310. install(instptr)
  311.    INSTAB *instptr;
  312. {
  313.    UINT i;
  314.  
  315.    i = (instptr->opcode) % HASHVAL;
  316.    instptr->next = hashtable[i];
  317.    hashtable[i] = instptr;
  318. }
  319.  
  320.  
  321. /* adapted from print_address in printcmd by R. Trawick 5/15/89.  The two should
  322.    be combined.
  323.  */
  324.  
  325. void sprint_address (addr, buffer)
  326.  
  327.      CORE_ADDR  addr;
  328.      char    *buffer;
  329.  
  330. {
  331.     struct minimal_symbol *msymbol;
  332.     struct symbol    *fs;
  333.     char        *name;
  334.     int        name_location;
  335.  
  336.     sprintf ( buffer, "0x%x", addr);
  337.  
  338.     fs = find_pc_function (addr);
  339.  
  340.     if (!fs) {
  341.         msymbol = lookup_minimal_symbol_by_pc (addr);
  342.  
  343.         if (i == NULL) return;/* If nothing comes through, don't
  344.                    print anything symbolic */
  345.  
  346.         name = msymbol -> name;
  347.         name_location = msymbol -> address;
  348.     } else {
  349.         name = fs->name;
  350.         name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs));
  351.     }
  352.  
  353.     if (addr - name_location)
  354.         sprintf (buffer, " <%s+%d>", name, addr - name_location);
  355.     else
  356.         sprintf (buffer, " <%s>", name);
  357. }
  358.